package se.webbzon.boltzmann.resource;

import java.awt.Font;
import java.awt.Image;
import java.util.Map;

import se.webbzon.boltzmann.Main;
import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.oschi01.imageset.ImageSetLoader;
import se.webbzon.oschi01.modelset.Model3D;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.resourceset.ResourceSetLoaderException;
import se.webbzon.oschi01.sound.FiniteSoundSource;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.textureset.Texture3DSetLoader;

public class Resources {
	
	// Load fallbacks
	static {
		Texture3DSetLoader tBroken = new Texture3DSetLoader();
		ImageSetLoader iBroken = new ImageSetLoader();
		try {
			tBroken.addFromURL(Main.class.getClassLoader().getResource("loader/broken.png"));
			iBroken.addFromURL(Main.class.getClassLoader().getResource("loader/broken.png"));
		} catch (ResourceSetLoaderException e) {
			e.printStackTrace();
		}
		textureSetFallback = tBroken.getResourceSet();
		imageSetFallback = iBroken.getResourceSet();
	}
	
	// Alert in the debugger if the resource is not found
	private static boolean alertOnMiss = false;
	
	// A map containing all loaded texture sets
	private static Map<String,ResourceSet<Texture3D>> textureSetMap;
	private static ResourceSet<Texture3D> textureSetFallback;
	
	// A map containing all loaded image sets
	private static Map<String,ResourceSet<Image>> imageSetMap;
	private static ResourceSet<Image> imageSetFallback;
	
	// A map containing all loaded model sets
	private static Map<String,ResourceSet<Model3D>> modelSetMap;
	
	// A map containing all loaded sounds sources
	private static Map<String,FiniteSoundSource> soundMap;
	
	// A map containing all loaded font sources
	private static Map<String,Font> fontMap;
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Sets whatever this resource class is alerting when a resource
	 * is requested but not found. **/
	public static void setAlerting(boolean alertOnMiss) {
		Resources.alertOnMiss = alertOnMiss;
	}
	
	/** Returns whatever this resource class is alerting when a resource
	 * is requested but not found. **/
	public static boolean isAlerting() {
		return alertOnMiss;
	}
	
	/** Returns the texture set associated with the given name. **/
	public static ResourceSet<Texture3D> getTextureSet(String name) {
		return getResource(name,textureSetMap,textureSetFallback);
	}
	
	/** Sets the static texture set map to the given texture set map. **/
	public static void setTextureSetMap(Map<String,ResourceSet<Texture3D>> map) {
		textureSetMap = map;
	}
	
	/** Returns the image set associated with the given name. **/
	public static ResourceSet<Image> getImageSet(String name) {
		return getResource(name,imageSetMap,imageSetFallback);
	}
	
	/** Sets the static image set map to the given image set map. **/
	public static void setImageSetMap(Map<String,ResourceSet<Image>> map) {
		imageSetMap = map;
	}
	
	/** Returns the model set associated with the given name. **/
	public static ResourceSet<Model3D> getModelSet(String name) {
		return getResource(name,modelSetMap,null);
	}
	
	/** Sets the static model set map to the given model set map. **/
	public static void setModelSetMap(Map<String,ResourceSet<Model3D>> map) {
		modelSetMap = map;
	}
	
	/** Returns the sound source associated with the given name. **/
	public static FiniteSoundSource getSound(String name) {
		return getResource(name,soundMap,null);
	}
	
	/** Sets the static sound source map to the given sound source map. **/
	public static void setSoundMap(Map<String,FiniteSoundSource> map) {
		soundMap = map;
	}
	
	/** Returns the font associated with the given name. **/
	public static Font getFont(String name) {
		return getResource(name,fontMap,null);
	}
	
	/** Sets the static font map to the given font map. **/
	public static void setFontMap(Map<String,Font> map) {
		fontMap = map;
	}
	
	/*============================================================
	Private methods
	============================================================*/
	
	/** Retrieves a resource with the given name in a safe way. **/
	private static final <T> T getResource(String name, Map<String,T> map, T fallback) {
		T resource = map.get(name);
		if (resource == null) {
			if (alertOnMiss) {
				Exception e = new ResourceNotFoundException("Could not find the resource with the name: " + name);
				Debug.report(e);
			}
			return fallback;
		} else
			return resource;
	}

}
